home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 October: Mac OS SDK / Dev.CD Oct 00 SDK1.toast / Development Kits / Mac OS / Multiprocessing 2.1v2 SDK / Sample Code / MP Sort Picts 12⁄04⁄99 / CopyBlits Folder / CopyBlits.c next >
Encoding:
C/C++ Source or Header  |  1998-10-07  |  13.4 KB  |  526 lines  |  [TEXT/CWIE]

  1. /*  CopyBlits
  2.  
  3. File name: CopyBlits.c
  4. Function: Optimized CopyBits
  5. History: 5/26/94 Original by George A. Warner
  6. History: 10/7/98 Interlace code written
  7.  
  8. */
  9.  
  10. #define DO_LOCKING 0
  11.  
  12. #include "CopyBlits.h"
  13.  
  14. static CTabHandle gCTabHandle = nil;
  15. static UInt16 gCTab16[256];
  16. static UInt32 gCTab32[256];
  17.  
  18. // implementation
  19. void Set_ColorTable(CTabHandle pCTabHandle)
  20. {
  21.     if (gCTabHandle != pCTabHandle)
  22.     {
  23.         gCTabHandle = pCTabHandle;
  24.         if (pCTabHandle)
  25.         {
  26.             if ((*pCTabHandle)->ctSize >= 255)
  27.             {
  28.                 short index;
  29.                 for (index = 0;index < 256;index++)
  30.                 {
  31.                     RGBColor tRGBColor = (**pCTabHandle).ctTable[index].rgb;
  32.                     gCTab32[index] =     ((tRGBColor.red >> 8) << 16) +
  33.                                         ((tRGBColor.green >> 8) << 8) +
  34.                                         ((tRGBColor.blue >> 8) << 0);
  35.                     gCTab16[index] =     ((tRGBColor.red >> 11) << 10) +
  36.                                         ((tRGBColor.green >> 11) << 5) +
  37.                                         ((tRGBColor.blue >> 11) << 0);
  38.                 }
  39.             }
  40.         }
  41.     }
  42. }
  43.  
  44. // Generic routine that uses pixel size to determ which optimized routine to use
  45. // If you KNOW your depth you should call the approate routine yourself and skip
  46. // the subroutine/switch overhead.
  47.  
  48. void CopyBlits    (    const PixMapHandle srcPixMapHdl,
  49.                         const PixMapHandle dstPixMapHdl,
  50.                         const Rect *srcRect,
  51.                         const Rect *dstRect
  52. )
  53. {
  54.     if ((*srcPixMapHdl)->pixelSize == 8)
  55.     {
  56.         switch ((*dstPixMapHdl)->pixelSize)
  57.         {
  58.             case    8:
  59. //                CopyBlits8(srcPixMapHdl,dstPixMapHdl,srcRect,dstRect);
  60.                 CopyBlits8_8(srcPixMapHdl,dstPixMapHdl,srcRect,dstRect);
  61.                 break;
  62.             case    16:
  63.                 CopyBlits8_16(srcPixMapHdl,dstPixMapHdl,srcRect,dstRect);
  64.                 break;
  65.             case    32:
  66.                 CopyBlits8_32(srcPixMapHdl,dstPixMapHdl,srcRect,dstRect);
  67.                 break;
  68.             default:
  69.                 CopyBits((BitMap*) *srcPixMapHdl,(BitMap*) *dstPixMapHdl,srcRect,dstRect,0,nil);
  70.                 break;
  71.         }
  72.     }
  73.     else
  74.         CopyBits((BitMap*) *srcPixMapHdl,(BitMap*) *dstPixMapHdl,srcRect,dstRect,0,nil);
  75. }
  76.  
  77.  
  78. // This is one of the first non-asm blitters I ever saw. Not as fast as CopyBlits8_8 but I left
  79. // it in just to show you the skanky nested switch/while code (see Duff's device). ewueee!
  80.  
  81. // 194 fps vs. 300 fps CopyBits
  82. void CopyBlits8    (    const PixMapHandle srcPixMapHdl,
  83.                     const PixMapHandle dstPixMapHdl,
  84.                     const Rect *srcRect,
  85.                     const Rect *dstRect
  86. )
  87. {
  88.     long            dstLeft,dstRight;
  89.     long            *srcRow,*dstRow;
  90.     register long    *srcPtr,*dstPtr;
  91.     long            leftMask,rightMask;
  92.     long            notLeftMask,notRightMask;
  93.  
  94.     long            srcRowBytes;
  95.     long            dstRowBytes;
  96.     long            srcLeft;
  97.  
  98.     long            dstLong;
  99.     short            dstLongs;
  100.     short            height;
  101.     long            offset;
  102.     long            timesCopy;
  103.  
  104.     // This assumes that the pixmap is already locked
  105.     srcRow = (long *) (*srcPixMapHdl)->baseAddr;
  106.     dstRow = (long *) (*dstPixMapHdl)->baseAddr;
  107.     
  108.     // get the bit offset to the src left edge
  109.     srcLeft = (srcRect->left - (*srcPixMapHdl)->bounds.left) * (*srcPixMapHdl)->pixelSize;
  110.         
  111.     // offset the src ptr to the first long
  112.     srcRow += srcLeft >> 5;
  113.     
  114.     // get the bit offset to the dst left and right edges
  115.     dstLeft = (dstRect->left - (*dstPixMapHdl)->bounds.left) * (*dstPixMapHdl)->pixelSize;
  116.     dstRight = (dstRect->right - (*dstPixMapHdl)->bounds.left) * (*dstPixMapHdl)->pixelSize;
  117.     
  118.     // get the number of middle longs to do minus the left edge long
  119.     dstLongs = ((dstRight - dstLeft) >> 5) - 1;
  120.     
  121.     // offset the dst Ptr to the first long
  122.     dstRow += dstLeft >> 5;
  123.  
  124.     // now compute left and right masks for the dst
  125.     dstLeft &= 0x1f;
  126.     leftMask = ( 1 << dstLeft ) - 1;
  127.     notLeftMask = ~leftMask;
  128.     
  129.     dstRight &= 0x1f;
  130.     notRightMask = ( 1 << dstRight ) - 1;
  131.     rightMask = ~notRightMask;
  132.     
  133.     srcRowBytes = (*srcPixMapHdl)->rowBytes & 0x3fff;
  134.     dstRowBytes = (*dstPixMapHdl)->rowBytes & 0x3fff;
  135.  
  136.     // offset the src and dst ptrs to the first row
  137.     offset = (srcRect->top - (*srcPixMapHdl)->bounds.top) * srcRowBytes;
  138.     srcRow = (long*) ((Ptr) srcRow + offset);
  139.  
  140.     offset = (dstRect->top - (*dstPixMapHdl)->bounds.top) * dstRowBytes;
  141.     dstRow = (long*) ((Ptr) dstRow + offset);
  142.  
  143.     /* check if we need to do the left and right mask */
  144.     if ( leftMask )
  145.     {
  146.         if ( notLeftMask == 0 )
  147.         {
  148.             leftMask = 0;
  149.             dstLongs++;
  150.         }
  151.     }
  152.         
  153.     if ( rightMask )
  154.     {
  155.         if ( notRightMask == 0 )
  156.         {
  157.             rightMask = 0;
  158.             dstLongs++;
  159.         }
  160.     }
  161.  
  162.     height = srcRect->bottom - srcRect->top;    // No scaling allowed
  163.  
  164.     //for ( ; height >= 0; --height )
  165.     // changing the above 'for()' to the below 'while()' is what made this blit routine
  166.     // faster than CopyBits - a speed improvement equal to all other changes I had made
  167.     // previously.  (about 4 to 5 milliseconds, in case you were wondering)
  168.     // Lesson: the true bottlenecks are not always the obvious ones
  169.     while (height--)
  170.     {
  171.         srcPtr = srcRow;
  172.         dstPtr = dstRow;
  173.         
  174.         /* do the masked left edge */
  175.         if ( leftMask )
  176.         {
  177.             dstLong = *srcPtr++ & leftMask;
  178.             dstLong |= *dstPtr & notLeftMask;
  179.             *dstPtr++ = dstLong;
  180.         }
  181.  
  182.         /* do the middle longs with Duff's device */
  183.         timesCopy = (dstLongs + 15) >> 4;
  184.         
  185.         switch( dstLongs & 0xF )
  186.         {
  187.             case 0:    do
  188.                 {    *dstPtr++ = *srcPtr++;
  189.             case 15:    *dstPtr++ = *srcPtr++;
  190.             case 14:    *dstPtr++ = *srcPtr++;
  191.             case 13:    *dstPtr++ = *srcPtr++;
  192.             case 12:    *dstPtr++ = *srcPtr++;
  193.             case 11:    *dstPtr++ = *srcPtr++;
  194.             case 10:    *dstPtr++ = *srcPtr++;
  195.             case 9:        *dstPtr++ = *srcPtr++;
  196.             case 8:        *dstPtr++ = *srcPtr++;
  197.             case 7:        *dstPtr++ = *srcPtr++;
  198.             case 6:        *dstPtr++ = *srcPtr++;
  199.             case 5:        *dstPtr++ = *srcPtr++;
  200.             case 4:        *dstPtr++ = *srcPtr++;
  201.             case 3:        *dstPtr++ = *srcPtr++;
  202.             case 2:        *dstPtr++ = *srcPtr++;
  203.             case 1:        *dstPtr++ = *srcPtr++;
  204.                 } while( --timesCopy > 0 );
  205.         }
  206.  
  207.         /* do the masked right edge */
  208.         if ( rightMask )
  209.         {
  210.             dstLong = *srcPtr & rightMask;
  211.             dstLong |= *dstPtr & notRightMask;
  212.             *dstPtr = dstLong;
  213.         }
  214.         
  215.         /* bump to the next row */
  216.         srcRow = (long*) ((Ptr) srcRow + srcRowBytes);
  217.         dstRow = (long*) ((Ptr) dstRow + dstRowBytes);
  218.     }
  219. }
  220.  
  221. // my Fastest (non-asm) 8 to 8 bit blitter
  222.  
  223. // 354 fps vs. 300 fps CopyBits
  224. void CopyBlits8_8    (    const PixMapHandle srcPixMapHdl,
  225.                         const PixMapHandle dstPixMapHdl,
  226.                         const Rect *srcRect,
  227.                         const Rect *dstRect
  228. )
  229. {
  230.     UInt32    doubleCount,lineCount,count;
  231.     UInt8    startFlags, endFlags;
  232.     UInt8    *src, *dst;
  233.     UInt32    srcSkip, dstSkip;
  234.     UInt32    width,height;
  235.  
  236.     width = srcRect->right - srcRect->left;
  237.     height = srcRect->bottom - srcRect->top;
  238.  
  239.     if (!width || !height)
  240.         return;
  241.  
  242. #if DO_LOCKING
  243.     {
  244.         GWorldFlags srcGWFlags = GetPixelsState(srcPixMapHdl);
  245.         GWorldFlags dstGWFlags = GetPixelsState(dstPixMapHdl);
  246.  
  247.         if (0 == (srcGWFlags & pixelsLocked))    // if source not locked
  248.             if (!LockPixels(srcPixMapHdl))        // and we can't lock it
  249.                 return;    // give up
  250.  
  251.         if (0 == (dstGWFlags & pixelsLocked))    // if dest not locked
  252.             if (!LockPixels(dstPixMapHdl))        // and we can't lock it
  253.                 goto unlock;
  254. #endif
  255.  
  256.     srcSkip = (*srcPixMapHdl)->rowBytes & 0x3FFF;
  257.     dstSkip = (*dstPixMapHdl)->rowBytes & 0x3FFF;
  258.  
  259.     src = (UInt8*) GetPixBaseAddr(srcPixMapHdl) +
  260.         (srcSkip * (srcRect->top - (*srcPixMapHdl)->bounds.top)) +
  261.         srcRect->left - (*srcPixMapHdl)->bounds.left;
  262.     dst = (UInt8*) GetPixBaseAddr(dstPixMapHdl) +
  263.         (dstSkip * (dstRect->top - (*dstPixMapHdl)->bounds.top)) +
  264.         dstRect->left - (*dstPixMapHdl)->bounds.left;
  265.  
  266.     startFlags = ((UInt8 *) (((UInt32) src + 7U) & ~7U)) - src;
  267.     endFlags = ((UInt32) (src + width)) & 7U;
  268.     doubleCount = ((width - startFlags) - endFlags) / 8;
  269.  
  270.     // pre-fix skip values
  271.     srcSkip -= width;
  272.     dstSkip -= width;
  273.     
  274.     for (lineCount = 0; lineCount < height; lineCount++)
  275.     {
  276.         if (startFlags & 1)    // byte align
  277.             *dst++ = *src++;
  278.  
  279.         if (startFlags & 2)    // word align
  280.         {
  281.             *(UInt16*) dst = *(UInt16*) src;
  282.             src += 2;
  283.             dst += 2;
  284.         }
  285.  
  286.         if (startFlags & 4)    // long align
  287.         {
  288.             *(UInt32*) dst = *(UInt32*) src;
  289.             src += 4;
  290.             dst += 4;
  291.         }
  292.  
  293.         // copy doubles
  294.         for (count = 0; count < doubleCount; count++)
  295.         {
  296.             *(double*) dst = *(double*) src;
  297.             src += 8;
  298.             dst += 8;
  299.         }
  300.  
  301.         // copy remaining long
  302.         if (endFlags & 4)
  303.         {
  304.             *(UInt32*) dst = *(UInt32*) src;
  305.             src += 4;
  306.             dst += 4;
  307.         }
  308.             
  309.         // copy remaining word
  310.         if (endFlags & 2)
  311.         {
  312.             *(UInt16*) dst = *(UInt16*) src;
  313.             src += 2;
  314.             dst += 2;
  315.         }
  316.  
  317.         // copy remaining byte
  318.         if (endFlags & 1)
  319.             *dst++ = *src++;
  320.  
  321.         src += srcSkip;
  322.         dst += dstSkip;
  323.     }
  324. #if DO_LOCKING
  325. unlock:
  326.         if (0 == (srcGWFlags & pixelsLocked))    // if source wasn't locked
  327.             UnlockPixels(srcPixMapHdl);            // unlock it
  328.         if (0 == (dstGWFlags & pixelsLocked))    // if dest wasn't locked
  329.             UnlockPixels(dstPixMapHdl);            // unlock it
  330.     }
  331. #endif
  332. }
  333.  
  334. // my Fastest (non-asm) 8 to 16 bit blitter
  335.  
  336. // 50 fps vs. 42 fps CopyBits
  337. void CopyBlits8_16    (    const PixMapHandle srcPixMapHdl,
  338.                         const PixMapHandle dstPixMapHdl,
  339.                         const Rect *srcRect,
  340.                         const Rect *dstRect
  341. )
  342. {
  343.     UInt32    count;
  344.     UInt8    *src;
  345.     UInt16    *dst;
  346.     UInt32    srcSkip, dstSkip;
  347.     UInt32    width,height;
  348.  
  349.     Set_ColorTable((**srcPixMapHdl).pmTable);
  350.  
  351.     width = srcRect->right - srcRect->left;
  352.     height = srcRect->bottom - srcRect->top;
  353.  
  354.     if (!width || !height)
  355.         return;
  356.  
  357. #if DO_LOCKING
  358.     {
  359.         GWorldFlags srcGWFlags = GetPixelsState(srcPixMapHdl);
  360.         GWorldFlags dstGWFlags = GetPixelsState(dstPixMapHdl);
  361.  
  362.         if (0 == (srcGWFlags & pixelsLocked))    // if source not locked
  363.             if (!LockPixels(srcPixMapHdl))        // and we can't lock it
  364.                 return;    // give up
  365.  
  366.         if (0 == (dstGWFlags & pixelsLocked))    // if dest not locked
  367.             if (!LockPixels(dstPixMapHdl))        // and we can't lock it
  368.                 goto unlock;
  369. #endif
  370.  
  371.     srcSkip = (*srcPixMapHdl)->rowBytes & 0x3FFF;
  372.     dstSkip = (*dstPixMapHdl)->rowBytes & 0x3FFF;
  373.  
  374.     src = (UInt8*) (GetPixBaseAddr(srcPixMapHdl) +
  375.         (srcSkip * (srcRect->top - (*srcPixMapHdl)->bounds.top)) +
  376.         srcRect->left - (*srcPixMapHdl)->bounds.left);
  377.     dst = (UInt16*) (GetPixBaseAddr(dstPixMapHdl) +
  378.         (dstSkip * (dstRect->top - (*dstPixMapHdl)->bounds.top)) +
  379.         ((dstRect->left - (*dstPixMapHdl)->bounds.left) << 1));
  380.  
  381.     // pre-fix skip values
  382.     srcSkip -= width;
  383.     dstSkip -= width << 1;
  384.  
  385.     while (height--)
  386.     {
  387.         for (count = 0; count < width; count++)
  388.             *dst++ = gCTab16[*src++];
  389.         src += srcSkip;
  390.         dst = (UInt16*) (dstSkip + (Ptr) dst);
  391.     }
  392.  
  393. #if DO_LOCKING
  394. unlock:
  395.         if (0 == (srcGWFlags & pixelsLocked))    // if source wasn't locked
  396.             UnlockPixels(srcPixMapHdl);            // unlock it
  397.         if (0 == (dstGWFlags & pixelsLocked))    // if dest wasn't locked
  398.             UnlockPixels(dstPixMapHdl);            // unlock it
  399.     }
  400. #endif
  401. }
  402.  
  403. // my Fastest (non-asm) 8 to 32 bit blitter
  404.  
  405. // 50 fps vs. 39 fps CopyBits
  406. void CopyBlits8_32    (    const PixMapHandle srcPixMapHdl,
  407.                         const PixMapHandle dstPixMapHdl,
  408.                         const Rect *srcRect,
  409.                         const Rect *dstRect
  410. )
  411. {
  412.     register    UInt32    count;
  413.     register    UInt8    *src;
  414.     register    UInt32    *dst;
  415.     register    UInt32    srcSkip, dstSkip;
  416.     register    UInt32    width,height;
  417.  
  418.     Set_ColorTable((**srcPixMapHdl).pmTable);
  419.  
  420.     width = srcRect->right - srcRect->left;
  421.     height = srcRect->bottom - srcRect->top;
  422.  
  423.     if (!width || !height)
  424.         return;
  425.  
  426. #if DO_LOCKING
  427.     {
  428.         GWorldFlags srcGWFlags = GetPixelsState(srcPixMapHdl);
  429.         GWorldFlags dstGWFlags = GetPixelsState(dstPixMapHdl);
  430.  
  431.         if (0 == (srcGWFlags & pixelsLocked))    // if source not locked
  432.             if (!LockPixels(srcPixMapHdl))        // and we can't lock it
  433.                 return;    // give up
  434.  
  435.         if (0 == (dstGWFlags & pixelsLocked))    // if dest not locked
  436.             if (!LockPixels(dstPixMapHdl))        // and we can't lock it
  437.                 goto unlock;
  438. #endif
  439.  
  440.     srcSkip = (*srcPixMapHdl)->rowBytes & 0x3FFF;
  441.     dstSkip = (*dstPixMapHdl)->rowBytes & 0x3FFF;
  442.  
  443.     src = (UInt8*) (GetPixBaseAddr(srcPixMapHdl) +
  444.         (srcSkip * (srcRect->top - (*srcPixMapHdl)->bounds.top)) +
  445.         srcRect->left - (*srcPixMapHdl)->bounds.left);
  446.     dst = (UInt32*) (GetPixBaseAddr(dstPixMapHdl) +
  447.         (dstSkip * (dstRect->top - (*dstPixMapHdl)->bounds.top)) +
  448.         ((dstRect->left - (*dstPixMapHdl)->bounds.left) << 2));
  449.  
  450.     // pre-fix skip values
  451.     srcSkip -= width;
  452.     dstSkip -= width << 2;
  453.  
  454.     while (height--)
  455.     {
  456.         for (count = 0; count < width; count++)
  457.             *dst++ = gCTab32[*src++];
  458.         src += srcSkip;
  459.         dst = (UInt32*) (dstSkip + (Ptr) dst);
  460.     }
  461.  
  462. #if DO_LOCKING
  463. unlock:
  464.         if (0 == (srcGWFlags & pixelsLocked))    // if source wasn't locked
  465.             UnlockPixels(srcPixMapHdl);            // unlock it
  466.         if (0 == (dstGWFlags & pixelsLocked))    // if dest wasn't locked
  467.             UnlockPixels(dstPixMapHdl);            // unlock it
  468.     }
  469. #endif
  470. }
  471.  
  472. // Ok, here it is. This is how you fake CopyBits into skipping every other line.
  473. // (I assume that the PixMaps are already locked)
  474. void CopyBlitsI    (    const PixMapHandle srcPixMapHdl,
  475.                     const PixMapHandle dstPixMapHdl,
  476.                     const Rect *srcRect,
  477.                     const Rect *dstRect
  478. )
  479. {
  480.     PixMap sPixMap = **srcPixMapHdl;
  481.     PixMap dPixMap = **dstPixMapHdl;
  482.     Rect sRect = *srcRect;
  483.     Rect dRect = *dstRect;
  484.  
  485.     // backup one pixel
  486.     // This prevents QuickDraw from using a blitter that's optimized
  487.     // to go directly to VRAM (which ignores our slammed rowbytes)
  488.     {
  489.         sPixMap.baseAddr -= sPixMap.pixelSize / 8;
  490.         dPixMap.baseAddr -= dPixMap.pixelSize / 8;
  491.         sPixMap.bounds.left--; sPixMap.bounds.right--;
  492.         dPixMap.bounds.left--; dPixMap.bounds.right--;
  493.     }
  494.  
  495.     // double source rowbytes (keep top two flags)
  496.     sPixMap.rowBytes = (sPixMap.rowBytes & 0xC000) | 
  497.         ((sPixMap.rowBytes << 1) & 0x3FFF);
  498.  
  499.     // double destination rowbytes (keep top two flags)
  500.     dPixMap.rowBytes = (dPixMap.rowBytes & 0xC000) | 
  501.         ((dPixMap.rowBytes << 1) & 0x3FFF);
  502.  
  503.     // half source rect heights
  504.     sRect.bottom = (sRect.bottom - sPixMap.bounds.top) >> 1;
  505.     sRect.top = (sRect.top - sPixMap.bounds.top) >> 1;
  506.  
  507.     sPixMap.bounds.top >>= 1;
  508.     sPixMap.bounds.bottom >>= 1;
  509.  
  510.     sRect.bottom += sPixMap.bounds.top;
  511.     sRect.top += sPixMap.bounds.top;
  512.  
  513.     // half destination rect heights
  514.     dRect.bottom = (dRect.bottom - dPixMap.bounds.top) >> 1;
  515.     dRect.top = (dRect.top - dPixMap.bounds.top) >> 1;
  516.  
  517.     dPixMap.bounds.top >>= 1;
  518.     dPixMap.bounds.bottom >>= 1;
  519.  
  520.     dRect.bottom += dPixMap.bounds.top;
  521.     dRect.top += dPixMap.bounds.top;
  522.  
  523.     // Copy it
  524.     CopyBits((BitMap*) &sPixMap,(BitMap*) &dPixMap,&sRect,&dRect,srcCopy,nil);
  525. }
  526.